package com.netnovelstore.annotation.impl;

import com.netnovelstore.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.UndeclaredThrowableException;
import java.util.StringJoiner;

@Aspect
@Component
@Slf4j
@Order(1)
public class ResultInterceptorImpl {

    @Pointcut("@annotation(com.netnovelstore.annotation.ResultInterceptor)")
    public void methodInterPoint() {
    }


    @Around("methodInterPoint()")

    public Result methodProcessing(ProceedingJoinPoint joinPoint) {
        return this.processing(joinPoint);
    }

    @Around(value = "@within(com.netnovelstore.annotation.ResultInterceptor)")
    public Result classProcessing(ProceedingJoinPoint joinPoint) {
        return this.processing(joinPoint);
    }

    private Result processing(ProceedingJoinPoint joinPoint) {
        try {
            log.info("run ResultInterceptorImpl");
            return (Result) joinPoint.proceed();
        } catch (UndeclaredThrowableException e) {
            log.error(e.getCause().getMessage());
            this.printStackTrace(e.getStackTrace());
            return Result.defeat(false, e.getCause().getMessage());
        } catch (Throwable e) {
            this.printStackTrace(e.getStackTrace());
            return Result.defeat(e.toString());
        }
    }

    private void printStackTrace(StackTraceElement[] stackTrace) {

        String tableHead = "\n-----------------------error------[" + this.getClass().toString() + "]-----------------------\n";
        StringJoiner stringJoiner = new StringJoiner("\n", tableHead, tableHead);
        for (StackTraceElement traceElement : stackTrace)
            stringJoiner.add(traceElement.toString());
        log.error(stringJoiner.toString());
    }
}
